﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Reflection;

namespace DBA.Common
{
    public static class PropertyHelper
    {
        /// <summary>
        /// 判断一个属性是否包含在实体类中,并返回此属性的反射信息
        /// </summary>
        /// <typeparam name="T">实体类名</typeparam>
        /// <param name="Name">要判断的属性</param>
        /// <param name="obj">实体类实例</param>
        /// <returns></returns>
        public static PropertyInfo FindProName<T>(string Name, T obj)
        {
            foreach (PropertyInfo pro in obj.GetType().GetProperties())
            {
                if (pro.Name.ToLower() == Name.ToLower())
                {
                    return pro;
                }
            }
            return null;
            //PropertyInfo propertyInfo = null;

        }

        /// <summary>
        /// 返回一个实体类的属性名，
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="Name">要查询的对象名</param>
        /// <param name="obj">对象实体</param>
        /// <param name="isUpperOrLower">是否分大小写</param>
        /// <returns></returns>
        public static PropertyInfo FindByName<T>(string Name, T obj, bool isUpperOrLower)
        {
            if (isUpperOrLower)
            {
                return obj.GetType().GetProperties().FirstOrDefault(p => p.Name == Name);
            }
            return obj.GetType().GetProperties().FirstOrDefault(p => p.Name.ToLower() == Name.ToLower()); 
        }

        public static void FindAndSetValueByName<T>(string name, T obj, string txtValue, bool isUpperOrLower)
        {
            PropertyInfo proInfo = null;
            if (isUpperOrLower)
            {
                proInfo = obj.GetType().GetProperties().FirstOrDefault(p => p.Name == name);
            }
            else
            {
                proInfo = obj.GetType().GetProperties().FirstOrDefault(p => p.Name.ToLower() == name.ToLower());
            }
            if (proInfo != null)
            {
                SecurityConvertToValue<T>(obj, proInfo, txtValue);
            }
            
        }

        public static void SecurityConvertToValue<T>(T input, PropertyInfo property,object value)
        {
            switch (property.PropertyType.Name.ToLower())
            {
                case "byte":
                    property.FastSetValue<T>(input, ConvertHelper.ToByte(value));
                    //property.SetValue(input, ConvertHelper.ToByte(pair.Value), null);
                    break;

                case "int16":
                    property.FastSetValue<T>(input, ConvertHelper.ToInt16(value));
                    //property.SetValue(input, ConvertHelper.ToInt16(pair.Value), null);
                    break;

                case "int32":
                    property.FastSetValue<T>(input, ConvertHelper.ToInt32(value));
                    //property.SetValue(input, ConvertHelper.ToInt32(pair.Value), null);
                    break;

                case "int64":
                    property.FastSetValue<T>(input, ConvertHelper.ToInt64(value));
                    //property.SetValue(input, ConvertHelper.ToInt64(pair.Value), null);
                    break;

                case "single":
                    property.FastSetValue<T>(input, ConvertHelper.ToSingle(value));
                    //property.SetValue(input, ConvertHelper.ToSingle(pair.Value), null);
                    break;

                case "double":
                    property.FastSetValue<T>(input, ConvertHelper.ToDouble(value));
                    //property.SetValue(input, ConvertHelper.ToDouble(pair.Value), null);
                    break;

                case "datetime":
                    property.FastSetValue<T>(input, ConvertHelper.ToDateTime(value));
                    //property.SetValue(input, ConvertHelper.ToDateTime(pair.Value), null);
                    break;

                case "decimal":
                    property.FastSetValue<T>(input, ConvertHelper.ToDecimal(value));
                    //property.SetValue(input, ConvertHelper.ToDecimal(pair.Value), null);
                    break;

                case "boolean":
                    property.FastSetValue<T>(input, ConvertHelper.ToBoolean(value));
                    //property.SetValue(input, ConvertHelper.ToBoolean(pair.Value), null);
                    break;

                case "guid":
                    property.FastSetValue<T>(input, ConvertHelper.ToGuid(value));
                    //property.SetValue(input, ConvertHelper.ToGuid(pair.Value), null);
                    break;

                case "string":
                    property.FastSetValue<T>(input, value.ToString());
                    //property.SetValue(input, pair.Value.ToString(), null);
                    break;
            }
        }

        /// <summary>
        /// 得到属性的一个集合
        /// </summary>
        /// <param name="input">输入类</param>
        /// <returns></returns>
        public static PropertyInfo[] GetProperties(object input)
        {
            return input.GetType().GetProperties();
        }

        /// <summary>
        /// 根据一个属性集合
        /// </summary>
        /// <param name="input"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static PropertyInfo GetProperty(object input, string propertyName)
        {
            return input.GetType().GetProperty(propertyName);
        }

        /// <summary>
        /// 得到值
        /// </summary>
        /// <param name="input"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static object GetValue(object input, string propertyName)
        {
            return GetProperty(input, propertyName).GetValue(input,null);
        }

        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="input"></param>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        public static void SetValue(object input, string propertyName, object value)
        {
            GetProperty(input, propertyName).SetValue(input, value, null);
        }

        /// <summary>
        /// 快速设置对象的值,比反射的速度快
        /// ,比反射的速度快y>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="t"></param>
        /// <param name="value"></param>
        public static void FastSetValue<T>(this PropertyInfo property, T t, object value)
        {
            MethodInfo m = property.GetSetMethod();
            ExpressionHelper.GetSetDelegate<T>(m, property.PropertyType)(t, m, value);
        }
        
        /// <summary>
        /// 快速得到对象的值,比反射的速度快      
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static object FastGetValue<T>(this PropertyInfo property, T t)
        {
            MethodInfo m = property.GetGetMethod();
            return ExpressionHelper.GetGetDelegate<T>(m, property.PropertyType)(t, m);
        }
    }
}
